﻿using SharpGL;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System;
using System.Collections;

namespace MutsiEngine
{
    public class Mesh : Object
    {
        public List<Vertex> VertexList;

        private uint displayList;

        // used for storing the id of the vbo
        uint[] vertexBufferObjectIds = new uint[1];

        IntPtr pIndices;
        

        public void CreateDisplayList(OpenGL gl)
        {
            displayList = gl.GenLists(1);
            gl.NewList(displayList, OpenGL.GL_COMPILE);

            gl.Begin(OpenGL.GL_TRIANGLES);
            for (int i = 0; i < VertexList.Count; i++)
            {
                gl.Normal(VertexList[i].Normal.X,VertexList[i].Normal.Y,VertexList[i].Normal.Z);
                gl.TexCoord(VertexList[i].TextureCoordinate.X,VertexList[i].TextureCoordinate.Y);
                gl.Vertex(VertexList[i].Position.X,VertexList[i].Position.Y,VertexList[i].Position.Z);
            }
            gl.End();

            gl.EndList();

            VertexList.Clear();
        }

        public void CreateVBO(OpenGL gl)
        {
            /*
            // create the buffer id
            gl.GenBuffers(1, vertexBufferObjectIds);
            // bind the buffer type to the id
            gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, vertexBufferObjectIds[0]);
            // I'm not sure if there is a better way to get a pointer to a float array, a quick Google search turned up this unsafe way
            unsafe
            {
                fixed (float* verts = MutsiMath.Vector3ListToFloat(Vertices))
                {
                     var pVertices = new IntPtr(verts);
                    // fill the buffer to the currently binded buffer
                     gl.BufferData(OpenGL.GL_ARRAY_BUFFER, Vertices.Count * sizeof(float) * 3, pVertices, OpenGL.GL_STATIC_DRAW);
                }
                fixed (float* normal = MutsiMath.Vector3ListToFloat(Normals))
                {
                    var pNormals = new IntPtr(normal);
                    // fill the buffer to the currently binded buffer
                    gl.BufferData(OpenGL.GL_NORMAL_ARRAY, Vertices.Count * sizeof(float) * 3, pNormals, OpenGL.GL_STATIC_DRAW);
                }
                /*fixed (float* verts = MutsiMath.Vector3ListToFloat(Vertices))
                {
                    var pVertices = new IntPtr(verts);
                    // fill the buffer to the currently binded buffer
                    gl.BufferData(OpenGL., Vertices.Count * sizeof(float) * 3, pVertices, OpenGL.GL_STATIC_DRAW);
                }
                fixed (int* indy = VertexIndicies.ToArray())
                {
                    pIndices = new IntPtr(indy);
                }
            }*/
        }
        public void Draw(OpenGL gl)
        {
            gl.CallList(displayList);
        }
        public void DrawVBO(OpenGL gl)
        {
            /*
            // bind to the buffer id we obtained earlier
            gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, vertexBufferObjectIds[0]);
            // enable proper vbo client state
            gl.EnableClientState(OpenGL.GL_VERTEX_ARRAY);
            gl.EnableVertexAttribArray(0);
            gl.VertexAttribPointer(0, 3, OpenGL.GL_FLOAT, false, 0, new IntPtr(0));

            // draw the current bound buffer with the specified indices
            gl.DrawElements(OpenGL.GL_TRIANGLES, VertexIndicies.Count, OpenGL.GL_UNSIGNED_INT, pIndices);
            */

            /*gl.EnableClientState(OpenGL.GL_VERTEX_ARRAY);
            gl.EnableClientState(OpenGL.GL_NORMAL_ARRAY);
            gl.EnableClientState(OpenGL.GL_TEXTURE_COORD_ARRAY);

            gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, vertexBufferObjectIds[0]);
            gl.VertexPointer(3, OpenGL.GL_FLOAT, 0, new IntPtr(0));
            gl.NormalPointer(OpenGL.GL_FLOAT, Marshal.SizeOf(Vertex), MutsiMath.Vector3ListToFloat(Normals));
            gl.TexCoordPointer(2, OpenGL.GL_FLOAT, Marshal.SizeOf(Vertex)*2f, MutsiMath.Vector2ListToFloat(TextureCoords));
            gl.DrawArrays(OpenGL.GL_TRIANGLES, 0, VertexIndicies.Count);
             * */
            //gl.DrawElements(OpenGL.GL_TRIANGLES, VertexIndicies.Count/3, OpenGL.GL_UNSIGNED_INT, pIndices);
        }
    }
}
